/*
 *  tracker/SectionQuickOptions.cpp
 *
 *  Copyright 2009 Peter Barth
 *
 *  This file is part of Milkytracker.
 *
 *  Milkytracker is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Milkytracker is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Milkytracker.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

/*
 *  SectionQuickOptions.cpp
 *  MilkyTracker
 *
 *  Created by Peter Barth on 10.05.05.
 *
 */

#include "SectionQuickOptions.h"
#include "Tracker.h"
#include "TrackerConfig.h"
#include "PlayerController.h"
#include "PlayerMaster.h"
#include "PlayerSTD.h"
#include "CheckBox.h"
#include "RadioGroup.h"
#include "StaticText.h"
#include "Seperator.h"
#include "Container.h"
#include "DialogPanning.h"

#include "ControlIDs.h"

enum ControlIDs
{
    CONTAINER_QUICKOPTIONS = 7000,
    QUICKOPTIONS_BUTTON_EXIT,
    QUICKOPTIONS_RADIOGROUP_PLAYBACKMODE,

    QUICKOPTIONS_STATICTEXT_ALLOW8XX,
    QUICKOPTIONS_CHECKBOX_ALLOW8XX,
    QUICKOPTIONS_STATICTEXT_ALLOWE8X,
    QUICKOPTIONS_CHECKBOX_ALLOWE8X,
    QUICKOPTIONS_STATICTEXT_PTPERIODRANGE,
    QUICKOPTIONS_CHECKBOX_PTPERIODRANGE,
    QUICKOPTIONS_STATICTEXT_SETDEFAULTPANNING,
    QUICKOPTIONS_BUTTON_SETDEFAULTPANNING,
    QUICKOPTIONS_STATICTEXT_KEEPOPTIONS,
    QUICKOPTIONS_CHECKBOX_KEEPOPTIONS,

    QUICKOPTIONS_CHECKBOX_FOLLOWSONG
};

SectionQuickOptions::SectionQuickOptions (Tracker& theTracker) :
    SectionUpperLeft(theTracker),
    checkBoxKeepSettings(NULL),
    dialogPanning(NULL),
    oldPanning(NULL)
{
}

SectionQuickOptions::~SectionQuickOptions ()
{
    delete[] oldPanning;
    delete dialogPanning;
}

pp_int32 SectionQuickOptions::handleEvent(PPObject* sender, PPEvent* event)
{
    bool b;

    if (event->getID() == eCommand || event->getID() == eCommandRepeat)
    {

        switch (reinterpret_cast<PPControl*>(sender)->getID())
        {
            case QUICKOPTIONS_BUTTON_EXIT:
                if (event->getID() != eCommand)
                    break;

                show(false);
                break;

            case QUICKOPTIONS_CHECKBOX_ALLOW8XX:
                if (event->getID() != eCommand)
                    break;

                b = tracker.playerController->isPlayModeOptionEnabled(PlayerController::PlayModeOptionPanning8xx);
                tracker.playerController->enablePlayModeOption(PlayerController::PlayModeOptionPanning8xx, !b);
                break;

            case QUICKOPTIONS_CHECKBOX_ALLOWE8X:
                if (event->getID() != eCommand)
                    break;

                b = tracker.playerController->isPlayModeOptionEnabled(PlayerController::PlayModeOptionPanningE8x);
                tracker.playerController->enablePlayModeOption(PlayerController::PlayModeOptionPanningE8x, !b);
                break;

            case QUICKOPTIONS_CHECKBOX_PTPERIODRANGE:
                if (event->getID() != eCommand)
                    break;

                b = tracker.playerController->isPlayModeOptionEnabled(PlayerController::PlayModeOptionForcePTPitchLimit);
                tracker.playerController->enablePlayModeOption(PlayerController::PlayModeOptionForcePTPitchLimit, !b);
                break;

            case QUICKOPTIONS_BUTTON_SETDEFAULTPANNING:
            {
                if (event->getID() != eCommand)
                    break;

                saveOldPanning();

                for (pp_int32 i = 0; i < TrackerConfig::numPlayerChannels; i++)
                    dialogPanning->setPanning((pp_uint8)i, tracker.playerController->getPanning((pp_uint8)i), false);

                dialogPanning->show(true);
                break;
            }

            case QUICKOPTIONS_CHECKBOX_KEEPOPTIONS:
                if (event->getID() != eCommand)
                    break;

                if (checkBoxKeepSettings->isChecked())
                    tracker.showMessageBoxSized(MESSAGEBOX_UNIVERSAL, "Play mode auto-switching is now OFF\nRemember, these settings will now\napply to all loaded modules.", Tracker::MessageBox_OK);
                break;
        }

    }
    else if (event->getID() == eSelection)
    {
        switch (reinterpret_cast<PPControl*>(sender)->getID())
        {
            case QUICKOPTIONS_RADIOGROUP_PLAYBACKMODE:
                switch (reinterpret_cast<PPRadioGroup*>(sender)->getChoice())
                {
                    case 0:
                        tracker.playerController->switchPlayMode(PlayerController::PlayMode_FastTracker2, !keepSettings());
                        static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_CHECKBOX_PTPERIODRANGE)->enable(false);
                        static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_STATICTEXT_PTPERIODRANGE)->enable(false);

                        static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_STATICTEXT_SETDEFAULTPANNING)->enable(false);
                        static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_BUTTON_SETDEFAULTPANNING)->enable(false);
                        break;
                    case 1:
                        tracker.playerController->switchPlayMode(PlayerController::PlayMode_ProTracker2, !keepSettings());
                        static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_CHECKBOX_PTPERIODRANGE)->enable(true);
                        static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_STATICTEXT_PTPERIODRANGE)->enable(true);

                        static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_STATICTEXT_SETDEFAULTPANNING)->enable(true);
                        static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_BUTTON_SETDEFAULTPANNING)->enable(true);
                        break;
                    case 2:
                        tracker.playerController->switchPlayMode(PlayerController::PlayMode_ProTracker3, !keepSettings());
                        static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_CHECKBOX_PTPERIODRANGE)->enable(true);
                        static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_STATICTEXT_PTPERIODRANGE)->enable(true);

                        static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_STATICTEXT_SETDEFAULTPANNING)->enable(true);
                        static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_BUTTON_SETDEFAULTPANNING)->enable(true);
                        break;
                    default:
                        ASSERT(false);
                }

                update();
                break;
        }

    }
    else if (event->getID() == eValueChanged &&
             reinterpret_cast<DialogPanning*>(sender) == dialogPanning)
    {
        pp_uint32 i = *(reinterpret_cast<const pp_uint32*>(event->getDataPtr()));

        tracker.playerController->setPanning((pp_uint8)i, dialogPanning->getPanning(i));
    }
    else if (event->getID() == eCanceled)
    {
        if (reinterpret_cast<DialogPanning*>(sender) == dialogPanning)
        {
            restoreOldPanning();
        }
    }

    return 0;
}

void SectionQuickOptions::init(pp_int32 px, pp_int32 py)
{
    PPCheckBox* checkBox;
    PPScreen* screen = tracker.screen;

    if (dialogPanning == NULL)
        dialogPanning = new DialogPanning(screen, this, TrackerConfig::numPlayerChannels);

    PPContainer* container = new PPContainer(CONTAINER_QUICKOPTIONS, tracker.screen, this, PPPoint(px, py), PPSize(320, UPPERLEFTSECTIONHEIGHT), false);
    container->setColor(TrackerConfig::colorThemeMain);
    tracker.screen->addControl(container);

    container->addControl(new PPStaticText(0, NULL, NULL, PPPoint(px + 2, py + 2), "Quick Options (experts only)", true, true));

    PPSize size = container->getSize();

    pp_int32 buttonWidth = 8 * 4 + 4;
    pp_int32 buttonHeight = 11;

    pp_int32 x = px + container->getSize().width - (buttonWidth + 4);
    pp_int32 y = py + container->getSize().height - (buttonHeight + 4);

    container->addControl(new PPSeperator(0, screen, PPPoint(x - 6, y - 4), 4 + buttonHeight + 3, TrackerConfig::colorThemeMain, false));
    container->addControl(new PPSeperator(0, screen, PPPoint(px + 2, y - 4), container->getSize().width - 4, TrackerConfig::colorThemeMain, true));

    PPButton* button = new PPButton(QUICKOPTIONS_BUTTON_EXIT, screen, this, PPPoint(x, y), PPSize(buttonWidth, buttonHeight));
    button->setText("Exit");
    container->addControl(button);

    pp_int32 x2 = px + 4;
    pp_int32 y2 = py + 4 + 12;

    y += 2;
    container->addControl(new PPStaticText(QUICKOPTIONS_STATICTEXT_KEEPOPTIONS, NULL, NULL, PPPoint(x2 + 2, y), "Keep settings (auto-adjust OFF)", true));
    checkBoxKeepSettings = new PPCheckBox(QUICKOPTIONS_CHECKBOX_KEEPOPTIONS, screen, this, PPPoint(x2 + 2 + 31 * 8 + 4, y - 1));
    checkBoxKeepSettings->checkIt(false);
    container->addControl(checkBoxKeepSettings);

    // add playback modes
    container->addControl(new PPStaticText(0, NULL, NULL, PPPoint(x2, y2), "Playback mode:", true));

    y2 += 10;

    PPRadioGroup* radioGroup = new PPRadioGroup(QUICKOPTIONS_RADIOGROUP_PLAYBACKMODE, screen, this, PPPoint(x2 + 2, y2), PPSize(17 * 8, 3 * 14));
    radioGroup->setColor(TrackerConfig::colorThemeMain);

    radioGroup->addItem("Fasttracker 2.x");
    radioGroup->addItem("Protracker 2.x");
    radioGroup->addItem("Protracker 3.x");

    container->addControl(radioGroup);

    y2 += radioGroup->getSize().height;

    x2 += radioGroup->getSize().width + 6;
    y2 = py + 16;
    container->addControl(new PPSeperator(0, screen, PPPoint(x2 - 4, y2 - 2), container->getLocation().y + container->getSize().height - y2 - 17, TrackerConfig::colorThemeMain, false));

    y2 = py + 4 + 12;
    x2 += 2;

    container->addControl(new PPStaticText(0, NULL, NULL, PPPoint(x2, y2), "Advanced:", true));

    y2 += 15;

    container->addControl(new PPStaticText(QUICKOPTIONS_STATICTEXT_ALLOW8XX, NULL, NULL, PPPoint(x2, y2), "Allow 8xx panning", true));
    checkBox = new PPCheckBox(QUICKOPTIONS_CHECKBOX_ALLOW8XX, screen, this, PPPoint(x2 + 19 * 8 + 4, y2 - 1));
    container->addControl(checkBox);

    y2 += 13;

    container->addControl(new PPStaticText(QUICKOPTIONS_STATICTEXT_ALLOWE8X, NULL, NULL, PPPoint(x2, y2), "Allow E8x panning", true));
    checkBox = new PPCheckBox(QUICKOPTIONS_CHECKBOX_ALLOWE8X, screen, this, PPPoint(x2 + 19 * 8 + 4, y2 - 1));
    container->addControl(checkBox);

    y2 += 13;

    container->addControl(new PPStaticText(QUICKOPTIONS_STATICTEXT_PTPERIODRANGE, NULL, NULL, PPPoint(x2, y2), "PT 3 octaves limit", true));
    checkBox = new PPCheckBox(QUICKOPTIONS_CHECKBOX_PTPERIODRANGE, screen, this, PPPoint(x2 + 19 * 8 + 4, y2 - 1));
    container->addControl(checkBox);

    y2 += 13;

    container->addControl(new PPStaticText(QUICKOPTIONS_STATICTEXT_SETDEFAULTPANNING, NULL, NULL, PPPoint(x2, y2), "Default panning", true));

    button = new PPButton(QUICKOPTIONS_BUTTON_SETDEFAULTPANNING, screen, this, PPPoint(x2 + 19 * 8 - 18, y2 - 1), PPSize(4 * 8, buttonHeight));
    button->setText("Set");
    container->addControl(button);

    sectionContainer = container;

    initialised = true;

    showSection(false);
}

void SectionQuickOptions::updateControlStates()
{
    switch (tracker.playerController->getPlayMode())
    {
        case PlayerBase::PlayMode_ProTracker2:
            static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_STATICTEXT_PTPERIODRANGE)->enable(true);
            static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_CHECKBOX_PTPERIODRANGE)->enable(true);
            static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_STATICTEXT_SETDEFAULTPANNING)->enable(true);
            static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_BUTTON_SETDEFAULTPANNING)->enable(true);
            break;

        case PlayerBase::PlayMode_ProTracker3:
            static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_STATICTEXT_PTPERIODRANGE)->enable(true);
            static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_CHECKBOX_PTPERIODRANGE)->enable(true);
            static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_STATICTEXT_SETDEFAULTPANNING)->enable(true);
            static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_BUTTON_SETDEFAULTPANNING)->enable(true);
            break;

        case PlayerBase::PlayMode_FastTracker2:
            static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_STATICTEXT_PTPERIODRANGE)->enable(false);
            static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_CHECKBOX_PTPERIODRANGE)->enable(false);
            static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_STATICTEXT_SETDEFAULTPANNING)->enable(false);
            static_cast<PPContainer*>(sectionContainer)->getControlByID(QUICKOPTIONS_BUTTON_SETDEFAULTPANNING)->enable(false);
            break;

        default:
            ASSERT(false);
    }
}

void SectionQuickOptions::show(bool bShow)
{
    if (bShow)
    {
        updateControlStates();
    }

    SectionUpperLeft::show(bShow);
}

void SectionQuickOptions::update(bool repaint /* = true*/)
{
    PPContainer* container = static_cast<PPContainer*>(sectionContainer);
    PPRadioGroup* radioGroup = static_cast<PPRadioGroup*>(container->getControlByID(QUICKOPTIONS_RADIOGROUP_PLAYBACKMODE));
    ASSERT(radioGroup);

    switch (tracker.playerController->getPlayMode())
    {
        case PlayerBase::PlayMode_ProTracker2:
            radioGroup->setChoice(1);
            break;

        case PlayerBase::PlayMode_ProTracker3:
            radioGroup->setChoice(2);
            break;

        case PlayerBase::PlayMode_FastTracker2:
            radioGroup->setChoice(0);
            break;

        default:
            ASSERT(false);
    }

    PPCheckBox* checkBox = static_cast<PPCheckBox*>(container->getControlByID(QUICKOPTIONS_CHECKBOX_ALLOW8XX));
    checkBox->checkIt(tracker.playerController->isPlayModeOptionEnabled(PlayerController::PlayModeOptionPanning8xx));

    checkBox = static_cast<PPCheckBox*>(container->getControlByID(QUICKOPTIONS_CHECKBOX_ALLOWE8X));
    checkBox->checkIt(tracker.playerController->isPlayModeOptionEnabled(PlayerController::PlayModeOptionPanningE8x));

    checkBox = static_cast<PPCheckBox*>(container->getControlByID(QUICKOPTIONS_CHECKBOX_PTPERIODRANGE));
    checkBox->checkIt(tracker.playerController->isPlayModeOptionEnabled(PlayerController::PlayModeOptionForcePTPitchLimit));

    if (repaint)
        tracker.screen->paintControl(container);
}

void SectionQuickOptions::notifyTabSwitch()
{
    if (sectionContainer->isVisible())
    {
        updateControlStates();
        update(false);
    }
}

bool SectionQuickOptions::setKeepSettings(bool b)
{
    if (checkBoxKeepSettings)
    {
        checkBoxKeepSettings->checkIt(b);
        return true;
    }

    return false;
}

bool SectionQuickOptions::keepSettings()
{
    if (checkBoxKeepSettings)
    {
        return checkBoxKeepSettings->isChecked();
    }

    return false;
}

void SectionQuickOptions::saveOldPanning()
{
    if (oldPanning == NULL)
        oldPanning = new pp_uint8[TrackerConfig::numPlayerChannels];

    for (pp_int32 i = 0; i < TrackerConfig::numPlayerChannels; i++)
        oldPanning[i] = tracker.playerController->getPanning((pp_uint8)i);
}

void SectionQuickOptions::restoreOldPanning()
{
    if (oldPanning == NULL)
        return;

    for (pp_int32 i = 0; i < TrackerConfig::numPlayerChannels; i++)
        tracker.playerController->setPanning((pp_uint8)i, oldPanning[i]);
}